package estore.service;

import estore.model.Product;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * 商品服务类，负责商品相关的业务逻辑
 * 支持数据持久化到文件，支持配置文件管理，支持数据备份
 */
public class ProductService {

    // 使用Map存储商品数据，key是商品ID，value是商品对象
    private final Map<String, Product> productData = new HashMap<>();

    // 数据文件路径（从配置文件读取）
    private String dataFilePath;

    /**
     * 构造函数，初始化商品数据
     */
    public ProductService() {
        // 先加载配置文件
        loadConfig();

        // 再尝试从文件加载数据
        if (!loadData()) {
            // 如果文件不存在或加载失败，初始化默认数据
            initDefaultData();
            System.out.println("使用默认商品数据初始化");
        } else {
            System.out.println("从文件加载商品数据成功，文件路径: " + dataFilePath);
        }
    }

    /**
     * 加载配置文件
     */
    private void loadConfig() {
        Properties prop = new Properties();
        File configFile = new File("config.properties");

        try (InputStreamReader reader = new InputStreamReader(
                new FileInputStream(configFile), "UTF-8")) {

            prop.load(reader);
            // 从配置文件中读取数据文件路径
            dataFilePath = prop.getProperty("data.file.path", "products.dat");

            System.out.println("配置文件加载成功，数据文件路径: " + dataFilePath);

        } catch (FileNotFoundException e) {
            // 如果配置文件不存在，使用默认值
            System.out.println("配置文件 config.properties 不存在，使用默认路径: products.dat");
            dataFilePath = "products.dat";
            // 可以在这里创建默认配置文件
            createDefaultConfig();
        } catch (IOException e) {
            System.out.println("读取配置文件失败: " + e.getMessage() + "，使用默认路径: products.dat");
            dataFilePath = "products.dat";
        }
    }

    /**
     * 创建默认配置文件（可选功能）
     */
    private void createDefaultConfig() {
        Properties prop = new Properties();
        prop.setProperty("data.file.path", "products.dat");

        try (OutputStreamWriter writer = new OutputStreamWriter(
                new FileOutputStream("config.properties"), "UTF-8")) {

            prop.store(writer, "E-Store Configuration File");
            System.out.println("已创建默认配置文件: config.properties");

        } catch (IOException e) {
            System.out.println("创建配置文件失败: " + e.getMessage());
        }
    }

    /**
     * 初始化默认商品数据，为部分商品添加标签
     */
    private void initDefaultData() {
        // 为Java书籍添加标签
        Set<String> tagsForJavaBook = new HashSet<>();
        tagsForJavaBook.add("编程");
        tagsForJavaBook.add("畅销");
        tagsForJavaBook.add("热门");
        productData.put("p001", new Product("p001", "Java从入门到精通", 99.0, 100, tagsForJavaBook));

        // 为MySQL书籍添加标签
        Set<String> tagsForMySQLBook = new HashSet<>();
        tagsForMySQLBook.add("数据库");
        tagsForMySQLBook.add("技术");
        tagsForMySQLBook.add("IT");
        productData.put("p002", new Product("p002", "高性能MySQL", 128.5, 50, tagsForMySQLBook));

        // 其他商品不使用标签
        productData.put("p003", new Product("p003", "颈椎康复指南", 45.0, 200));
        productData.put("p004", new Product("p004", "生发秘籍", 88.0, 0));

        // 验证标签的唯一性
        System.out.println("Java书籍标签数量（验证唯一性）: " + tagsForJavaBook.size());
        System.out.println("Java书籍标签内容: " + tagsForJavaBook);
    }

    /**
     * 保存商品数据到文件
     */
    public synchronized void saveData() {
        if (dataFilePath == null || dataFilePath.trim().isEmpty()) {
            System.out.println("错误：数据文件路径未配置");
            return;
        }

        // 创建备份
        File originalFile = new File(dataFilePath);
        if (originalFile.exists()) {
            createBackup();
        }

        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(dataFilePath))) {
            oos.writeObject(new HashMap<>(productData)); // 使用副本避免并发修改
            System.out.println("商品数据已保存到文件: " + dataFilePath);
        } catch (IOException e) {
            System.err.println("保存商品数据失败: " + e.getMessage());
            // 尝试恢复备份
            restoreBackup();
        }
    }

    /**
     * 从文件加载商品数据
     *
     * @return 加载成功返回true，失败返回false
     */
    @SuppressWarnings("unchecked")
    private boolean loadData() {
        if (dataFilePath == null || dataFilePath.trim().isEmpty()) {
            System.out.println("错误：数据文件路径未配置");
            return false;
        }

        File file = new File(dataFilePath);
        if (!file.exists()) {
            System.out.println("数据文件不存在，将使用默认数据");
            System.out.println("文件路径: " + dataFilePath);
            return false;
        }

        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(dataFilePath))) {
            Map<String, Product> loadedData = (Map<String, Product>) ois.readObject();
            productData.clear();
            productData.putAll(loadedData);
            System.out.println("成功加载 " + loadedData.size() + " 个商品数据");
            return true;
        } catch (IOException | ClassNotFoundException e) {
            System.out.println("加载商品数据失败: " + e.getMessage());
            System.out.println("文件路径: " + dataFilePath);
            return false;
        }
    }

    /**
     * 备份数据文件（使用底层字节流和缓冲区）
     *
     * @return 备份成功返回true，失败返回false
     */
    public boolean backupData() {
        if (dataFilePath == null || dataFilePath.trim().isEmpty()) {
            System.out.println("错误：数据文件路径未配置");
            return false;
        }

        File sourceFile = new File(dataFilePath);
        if (!sourceFile.exists()) {
            System.out.println("错误：源数据文件不存在，无法备份");
            System.out.println("文件路径: " + dataFilePath);
            return false;
        }

        String backupFilePath = dataFilePath + ".bak";
        File backupFile = new File(backupFilePath);

        // 使用最基础的FileInputStream和FileOutputStream进行备份
        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(backupFile)) {

            // 创建字节数组作为缓冲区
            byte[] buffer = new byte[1024];
            int bytesRead;
            long totalBytes = 0;

            System.out.println("开始备份数据文件...");
            System.out.println("源文件: " + dataFilePath);
            System.out.println("备份文件: " + backupFilePath);

            // 循环读取源文件并写入备份文件
            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
                totalBytes += bytesRead;

                // 显示备份进度（可选）
                if (totalBytes % (10 * 1024) == 0) {
                    System.out.println("已备份: " + totalBytes + " 字节");
                }
            }

            System.out.println("数据文件备份完成！");
            System.out.println("总备份大小: " + totalBytes + " 字节");
            System.out.println("备份文件路径: " + backupFilePath);

            // 验证备份文件是否创建成功
            if (backupFile.exists() && backupFile.length() == sourceFile.length()) {
                System.out.println("备份验证成功：备份文件大小与源文件一致");
                return true;
            } else {
                System.out.println("警告：备份文件可能不完整");
                return false;
            }

        } catch (FileNotFoundException e) {
            System.out.println("错误：文件未找到 - " + e.getMessage());
            return false;
        } catch (IOException e) {
            System.out.println("错误：备份过程中发生IO异常 - " + e.getMessage());
            return false;
        }
    }

    /**
     * 创建备份文件
     */
    private void createBackup() {
        String backupPath = dataFilePath + ".backup." + System.currentTimeMillis();
        try {
            Files.copy(Paths.get(dataFilePath), Paths.get(backupPath));
            System.out.println("创建备份文件: " + backupPath);
        } catch (IOException e) {
            System.err.println("创建备份失败: " + e.getMessage());
        }
    }

    /**
     * 恢复备份文件
     */
    private void restoreBackup() {
        // 查找最新的备份文件
        File dataFile = new File(dataFilePath);
        File backupDir = dataFile.getParentFile();
        String fileName = dataFile.getName();

        File[] backupFiles = backupDir.listFiles((dir, name) ->
                name.startsWith(fileName) && name.endsWith(".backup."));

        if (backupFiles != null && backupFiles.length > 0) {
            // 按修改时间排序，获取最新的备份
            File latestBackup = backupFiles[0];
            for (File backup : backupFiles) {
                if (backup.lastModified() > latestBackup.lastModified()) {
                    latestBackup = backup;
                }
            }

            try {
                Files.copy(latestBackup.toPath(), dataFile.toPath(),
                        java.nio.file.StandardCopyOption.REPLACE_EXISTING);
                System.out.println("从备份恢复数据: " + latestBackup.getName());
            } catch (IOException e) {
                System.err.println("恢复备份失败: " + e.getMessage());
            }
        }
    }

    /**
     * 获取配置文件中的路径（用于测试和调试）
     */
    public String getDataFilePath() {
        return dataFilePath;
    }

    /**
     * 获取备份文件路径
     */
    public String getBackupFilePath() {
        return dataFilePath + ".bak";
    }

    /**
     * 获取所有商品列表
     *
     * @return 商品列表
     */
    public List<Product> getAllProducts() {
        return new ArrayList<>(productData.values());
    }

    /**
     * 根据ID查找商品
     *
     * @param id 商品ID
     * @return 找到的商品对象，如果不存在则返回null
     */
    public Product findProductById(String id) {
        return productData.get(id);
    }

    /**
     * 添加商品
     */
    public String addProduct(Product product) {
        if (productData.containsKey(product.getId())) {
            return "ERROR: 商品ID已存在";
        }
        productData.put(product.getId(), product);
        saveData();
        return "SUCCESS: 商品添加成功";
    }

    /**
     * 更新商品
     */
    public String updateProduct(Product product) {
        if (!productData.containsKey(product.getId())) {
            return "ERROR: 商品不存在";
        }
        productData.put(product.getId(), product);
        saveData();
        return "SUCCESS: 商品更新成功";
    }

    /**
     * 删除商品
     */
    public String deleteProduct(String productId) {
        if (!productData.containsKey(productId)) {
            return "ERROR: 商品不存在";
        }
        productData.remove(productId);
        saveData();
        return "SUCCESS: 商品删除成功";
    }

    /**
     * 根据ID获取商品
     */
    public Product getProductById(String productId) {
        return productData.get(productId);
    }
}